package jvm;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * 代理实例的方法调用处理器（InvocationHandler）
 */
public class CustomInvocationHandler implements InvocationHandler {
    // 可选属性，用于在处理代理实例的方法调用时记录日志
    private Log log = LogFactory.getLog(this.getClass());
    /** 目标对象 */
    private Object target;

    public CustomInvocationHandler(Object target) {
        this.target = target;
    }

    /**
     * 根据目标对象，生成目标类实现的所有接口的代理实例
     * @param target 目标对象
     * @return Object 代理实例
     */
    public Object bind() {
        // 使用代理（Proxy）类生成一个新的代理实例
        // 返回指定接口的代理实例，该实例将方法调用分派到指定的调用处理器
        return Proxy.newProxyInstance(
            // 目标类的类加载器
            target.getClass().getClassLoader(),
            // 目标所属类或接口直接实现的接口列表
            target.getClass().getInterfaces(),
            // 将方法调用派发给当前调用处理程序
            this);
    }

    /**
     * 在代理实例调用方法时自动调用此方法，并返回结果
     * <p>当一个方法被调用到与之相关联的代理实例上时，该方法将被调用到调用处理程序上
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result = null;
        if (method.hashCode() % 2 == 0) {
            log.info("代理实例调用的方法的哈希值是偶数，执行");
            // 返回方法在调用返回的值
            result = method.invoke(target, args);
        } else {
            log.info("代理实例调用的方法的哈希值是奇数，不执行");
        }
        return result;
    }
}
